package cse.om.vswn;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import cse.om.common.UTF8File;
import edu.stanford.nlp.ling.WordTag;
import java.util.ArrayList;
import java.util.List;

public class VietSentiWordNet {

	private static final String _pathToVSWN = "resources/om/VietSentiWordnet_ver1.0.txt";
	private static final String _pathToNegativeWord = "resources/om/negative.txt";
	private static Map<String, Sensitivity> _dict;
	private static Set<String> _negativeWord;

	private static final String[] POS = {"v", "a", "n", "r"};

	static {
		try {
			init();
			readNegativeWord();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}

	private static void init() throws Exception {

		_dict = new HashMap<>();
		HashMap<String, Vector<Double>> temp = new HashMap<>();
		BufferedReader csv = null;

		try {
			csv = new BufferedReader(new FileReader(_pathToVSWN));
		} catch (FileNotFoundException e) {
			System.out.println("Không tìm thấy file " + _pathToVSWN + "!");
		}

		if (csv == null) {
			return;
		}

		String line = "";
		while ((line = csv.readLine()) != null) {
			if (line.charAt(0) == '#') {
				continue;
			}

			String[] data = line.split("\t");
			Double score = Double.parseDouble(data[2]) - Double.parseDouble(data[3]);
			String[] words = data[4].split(" ");

			String prev = "";
			for (String w : words) {
				if (w.contains("#")) {
					String[] w_n = (prev + w).split("#");
					w_n[0] += "#" + data[0];
					prev = "";

					int index = Integer.parseInt(w_n[1]) - 1;
					Vector<Double> v;
					if (temp.containsKey(w_n[0])) {
						v = temp.get(w_n[0]);
					} else {
						v = new Vector<>();
					}
					for (int i = v.size(); i < index; ++i) {
						v.add(0.0);
					}
					v.add(index, score);
					temp.put(w_n[0], v);
				} else {
					prev = prev + w + "_";
				}
			}
		}

		Set<String> keys = temp.keySet();
		for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
			String word = (String) iterator.next();
			Vector<Double> v = temp.get(word);
			double score = 0.0, sum = 0.0;
			for (int i = 0; i < v.size(); ++i) {
				score += (1.0 / (i + 1)) * v.get(i);
				sum += 1.0 / (i + 1);
			}
			score /= sum;

			Sensitivity s = new Sensitivity(score, word);
			_dict.put(word, s);
		}

		csv.close();
	}

	private static void readNegativeWord() throws IOException {
		_negativeWord = new HashSet<>();
		String[] words = UTF8File.getAllLines(_pathToNegativeWord);
		for (String w : words) {
			if (w.length() > 0) {
				_negativeWord.add(w);
			}
		}
	}

	public static Sensitivity extract(String word, String pos) {
		Sensitivity senti = extract(word + "#" + pos);
		if (senti.isNotDetermined()) {
			for (int i = 0; i < POS.length && senti.isNotDetermined(); ++i) {
				senti = extract(word + "#" + POS[i]);
			}
		}
		return senti;
	}

	public static Sensitivity extract(String word) {
		Sensitivity s = _dict.get(word);
		if (s != null) {
//			s.setWord(word);
			return s;
		} else {
			return new Sensitivity(null, word);
		}
	}

	public static Map<String, Sensitivity> extract(String[] words) {
		Map<String, Sensitivity> map = new HashMap<>();
		String prev = "";
		for (String word : words) {
			String[] w = word.split("#");
			Sensitivity senti = extract(w[0], w[1]);
			if (senti.isNotDetermined() == false) {
				if (_negativeWord.contains(prev)) {
					map.put(prev + " " + w[0], senti.getOpposite(prev + " "));
				} else {
					map.put(w[0], senti);
				}
			}
			prev = w[0];
		}
		return map;
	}

	public static List<Sensitivity> extract(List<List<WordTag>> wordTags) {
		List<Sensitivity> result = new ArrayList<>();
		for (List<WordTag> lwt : wordTags) {
			String prev = "";
			for (WordTag wt : lwt) {
				Sensitivity senti = extract(wt.word(), wt.tag());
				if (senti.isNotDetermined() == false) {
					if (_negativeWord.contains(prev)) {
						result.add(senti.getOpposite(prev + " "));
					} else {
						result.add(senti);
					}
				}
				prev = wt.word();
			}
		}
		return result;
	}
}
